﻿using System;
using System.Collections.Generic;
using System.Text;
using model=Co9320.NamaAlert.Model;

namespace KeyWordSearch.Normalization
{




	public static class Normalizer
	{
		[Flags]
		private enum CharacterType : byte
		{
			None = 0x00,
			HasSoundMarkedVariant = 0x01,
			HasSemiSoundMarkedVariant = 0x02,
			HasBothSoundMarkVariant = HasSoundMarkedVariant | HasSemiSoundMarkedVariant,
			SoundMark = 0x04,
			SemiSoundMark = 0x08,
			AllSoundMarks = SoundMark | SemiSoundMark,
			HasNoVariant = 0x10
		}

		private class CharacterData
		{
			public CharacterData(char Character,CharacterType Type)
			{
				this.Character=Character;
				this.Type=Type;
			}

			public char Character
			{
				get;
				private set;
			}

			public CharacterType Type
			{
				get;
				private set;
			}
		}

		private static SortedList<char, char> AlphaNumericConvDict_ = new SortedList<char, char>();
		private static SortedList<char, CharacterData> KanaConvDict_ = new SortedList<char, CharacterData>();

		private static SortedList<char, char> SemiSoundConverter_ = new SortedList<char, char>();
		private static SortedList<char, char> SoundConverter_ = new SortedList<char, char>();

		static Normalizer()
		{
			#region SoundConverter

			SoundConverter_.Add('カ', 'ガ'); // カ -> ガ
			SoundConverter_.Add('キ', 'ギ'); // キ -> ギ
			SoundConverter_.Add('ク', 'グ'); // ク -> グ
			SoundConverter_.Add('ケ', 'ゲ'); // ケ -> ゲ
			SoundConverter_.Add('コ', 'ゴ'); // コ -> ゴ

			SoundConverter_.Add('サ', 'ザ'); // サ -> ザ
			SoundConverter_.Add('シ', 'ジ'); // シ -> ジ
			SoundConverter_.Add('ス', 'ズ'); // ス -> ズ
			SoundConverter_.Add('セ', 'ゼ'); // セ -> ゼ
			SoundConverter_.Add('ソ', 'ゾ'); // ソ -> ゾ

			SoundConverter_.Add('タ', 'ダ'); // タ -> ダ
			SoundConverter_.Add('チ', 'ヂ'); // チ -> ヂ
			SoundConverter_.Add('ツ', 'ヅ'); // ツ -> ヅ
			SoundConverter_.Add('テ', 'デ'); // テ -> デ
			SoundConverter_.Add('ト', 'ド'); // ト -> ド

			SoundConverter_.Add('ハ', 'バ'); // ハ -> バ
			SoundConverter_.Add('ヒ', 'ビ'); // ヒ -> ビ
			SoundConverter_.Add('フ', 'ブ'); // フ -> ブ
			SoundConverter_.Add('ヘ', 'ベ'); // ヘ -> ベ
			SoundConverter_.Add('ホ', 'ボ'); // ホ -> ボ

			SoundConverter_.Add('ウ', 'ヴ'); // ウ -> ヴ

			#endregion 


			#region SemiSoundConverter

			SemiSoundConverter_.Add('ハ', 'パ');
			SemiSoundConverter_.Add('ヒ', 'ピ');
			SemiSoundConverter_.Add('フ', 'プ');
			SemiSoundConverter_.Add('ヘ', 'ペ');
			SemiSoundConverter_.Add('ホ', 'ポ');

			#endregion


			#region AlphaNumericDictionar

			AlphaNumericConvDict_.Add('　', ' '); // FullWidthSpace -> HalfWidthSpace
			AlphaNumericConvDict_.Add('，', ','); // ， -> ,
			AlphaNumericConvDict_.Add('．', '.'); // ． -> .
			AlphaNumericConvDict_.Add('：', ':'); // ： -> :
			AlphaNumericConvDict_.Add('；', ';'); // ； -> ;
			AlphaNumericConvDict_.Add('？', '?'); // ？ -> ?
			AlphaNumericConvDict_.Add('！', '!'); // ！ -> *
			AlphaNumericConvDict_.Add('´', '`'); // ´ -> `
			AlphaNumericConvDict_.Add('｀', '`'); // ｀ -> `
			AlphaNumericConvDict_.Add('＾', '^'); // ＾ -> ^
			AlphaNumericConvDict_.Add('＿', '_'); // ＿ -> _
			AlphaNumericConvDict_.Add('～', '~'); // ～ -> ~
			AlphaNumericConvDict_.Add('｜', '|'); // ｜ -> |
			AlphaNumericConvDict_.Add('‘', '\''); // ‘ -> '
			AlphaNumericConvDict_.Add('’', '\''); // ’ -> '
			AlphaNumericConvDict_.Add('“', '"'); // “ -> "
			AlphaNumericConvDict_.Add('”', '"'); // ” -> "
			AlphaNumericConvDict_.Add('（', '('); // （ -> (
			AlphaNumericConvDict_.Add('）', ')'); // ） -> )
			AlphaNumericConvDict_.Add('［', '['); // ［ -> [
			AlphaNumericConvDict_.Add('］', ']'); // ］ -> ]
			AlphaNumericConvDict_.Add('｛', '{'); // ｛ -> {
			AlphaNumericConvDict_.Add('｝', '}'); // ｝ -> }
			AlphaNumericConvDict_.Add('＋', '+'); // ＋ -> +
			AlphaNumericConvDict_.Add('－', '-'); // － -> -
			AlphaNumericConvDict_.Add('＝', '='); // ＝ -> =
			AlphaNumericConvDict_.Add('＜', '<'); // ＜ -> <
			AlphaNumericConvDict_.Add('＞', '>'); // ＞ -> >
			AlphaNumericConvDict_.Add('＄', '$'); // ＄ -> $
			AlphaNumericConvDict_.Add('％', '%'); // ％ -> %
			AlphaNumericConvDict_.Add('＃', '#'); // ＃ -> #
			AlphaNumericConvDict_.Add('＆', '&'); // ＆ -> &
			AlphaNumericConvDict_.Add('＊', '*'); // ＊ -> *
			AlphaNumericConvDict_.Add('＠', '@'); // ＠ -> @
			AlphaNumericConvDict_.Add('０', '0'); // ０ -> 0
			AlphaNumericConvDict_.Add('１', '1'); // １ -> 1
			AlphaNumericConvDict_.Add('２', '2'); // ２ -> 2
			AlphaNumericConvDict_.Add('３', '3'); // ３ -> 3
			AlphaNumericConvDict_.Add('４', '4'); // ４ -> 4
			AlphaNumericConvDict_.Add('５', '5'); // ５ -> 5
			AlphaNumericConvDict_.Add('６', '6'); // ６ -> 6
			AlphaNumericConvDict_.Add('７', '7'); // ７ -> 7
			AlphaNumericConvDict_.Add('８', '8'); // ８ -> 8
			AlphaNumericConvDict_.Add('９', '9'); // ９ -> 9
			AlphaNumericConvDict_.Add('Ａ', 'A'); // Ａ -> A
			AlphaNumericConvDict_.Add('Ｂ', 'B'); // Ｂ -> B
			AlphaNumericConvDict_.Add('Ｃ', 'C'); // Ｃ -> C
			AlphaNumericConvDict_.Add('Ｄ', 'D'); // Ｄ -> D
			AlphaNumericConvDict_.Add('Ｅ', 'E'); // Ｅ -> E
			AlphaNumericConvDict_.Add('Ｆ', 'F'); // Ｆ -> F
			AlphaNumericConvDict_.Add('Ｇ', 'G'); // Ｇ -> G
			AlphaNumericConvDict_.Add('Ｈ', 'H'); // Ｈ -> H
			AlphaNumericConvDict_.Add('Ｉ', 'I'); // Ｉ -> I
			AlphaNumericConvDict_.Add('Ｊ', 'J'); // Ｊ -> J
			AlphaNumericConvDict_.Add('Ｋ', 'K'); // Ｋ -> K
			AlphaNumericConvDict_.Add('Ｌ', 'L'); // Ｌ -> L
			AlphaNumericConvDict_.Add('Ｍ', 'M'); // Ｍ -> M
			AlphaNumericConvDict_.Add('Ｎ', 'N'); // Ｎ -> N
			AlphaNumericConvDict_.Add('Ｏ', 'O'); // Ｏ -> O
			AlphaNumericConvDict_.Add('Ｐ', 'P'); // Ｐ -> P
			AlphaNumericConvDict_.Add('Ｑ', 'Q'); // Ｑ -> Q
			AlphaNumericConvDict_.Add('Ｒ', 'R'); // Ｒ -> R
			AlphaNumericConvDict_.Add('Ｓ', 'S'); // Ｓ -> S
			AlphaNumericConvDict_.Add('Ｔ', 'T'); // Ｔ -> T
			AlphaNumericConvDict_.Add('Ｕ', 'U'); // Ｕ -> U
			AlphaNumericConvDict_.Add('Ｖ', 'V'); // Ｖ -> V
			AlphaNumericConvDict_.Add('Ｗ', 'W'); // Ｗ -> W
			AlphaNumericConvDict_.Add('Ｘ', 'X'); // Ｘ -> X
			AlphaNumericConvDict_.Add('Ｙ', 'Y'); // Ｙ -> Y
			AlphaNumericConvDict_.Add('Ｚ', 'Z'); // Ｚ -> Z
			AlphaNumericConvDict_.Add('ａ', 'A'); // ａ -> A
			AlphaNumericConvDict_.Add('ｂ', 'B'); // ｂ -> B
			AlphaNumericConvDict_.Add('ｃ', 'C'); // ｃ -> C
			AlphaNumericConvDict_.Add('ｄ', 'D'); // ｄ -> D
			AlphaNumericConvDict_.Add('ｅ', 'E'); // ｅ -> E
			AlphaNumericConvDict_.Add('ｆ', 'F'); // ｆ -> F
			AlphaNumericConvDict_.Add('ｇ', 'G'); // ｇ -> G
			AlphaNumericConvDict_.Add('ｈ', 'H'); // ｈ -> H
			AlphaNumericConvDict_.Add('ｉ', 'I'); // ｉ -> I
			AlphaNumericConvDict_.Add('ｊ', 'J'); // ｊ -> J
			AlphaNumericConvDict_.Add('ｋ', 'K'); // ｋ -> K
			AlphaNumericConvDict_.Add('ｌ', 'L'); // ｌ -> L
			AlphaNumericConvDict_.Add('ｍ', 'M'); // ｍ -> M
			AlphaNumericConvDict_.Add('ｎ', 'N'); // ｎ -> N
			AlphaNumericConvDict_.Add('ｏ', 'O'); // ｏ -> O
			AlphaNumericConvDict_.Add('ｐ', 'P'); // ｐ -> P
			AlphaNumericConvDict_.Add('ｑ', 'Q'); // ｑ -> Q
			AlphaNumericConvDict_.Add('ｒ', 'R'); // ｒ -> R
			AlphaNumericConvDict_.Add('ｓ', 'S'); // ｓ -> S
			AlphaNumericConvDict_.Add('ｔ', 'T'); // ｔ -> T
			AlphaNumericConvDict_.Add('ｕ', 'U'); // ｕ -> U
			AlphaNumericConvDict_.Add('ｖ', 'V'); // ｖ -> V
			AlphaNumericConvDict_.Add('ｗ', 'W'); // ｗ -> W
			AlphaNumericConvDict_.Add('ｘ', 'X'); // ｘ -> X
			AlphaNumericConvDict_.Add('ｙ', 'Y'); // ｙ -> Y
			AlphaNumericConvDict_.Add('ｚ', 'Z'); // ｚ -> Z
			AlphaNumericConvDict_.Add('a', 'A'); // a -> A
			AlphaNumericConvDict_.Add('b', 'B'); // b -> B
			AlphaNumericConvDict_.Add('c', 'C'); // c -> C
			AlphaNumericConvDict_.Add('d', 'D'); // d -> D
			AlphaNumericConvDict_.Add('e', 'E'); // e -> E
			AlphaNumericConvDict_.Add('f', 'F'); // f -> F
			AlphaNumericConvDict_.Add('g', 'G'); // g -> G
			AlphaNumericConvDict_.Add('h', 'H'); // h -> H
			AlphaNumericConvDict_.Add('i', 'I'); // i -> I
			AlphaNumericConvDict_.Add('j', 'J'); // j -> J
			AlphaNumericConvDict_.Add('k', 'K'); // k -> K
			AlphaNumericConvDict_.Add('l', 'L'); // l -> L
			AlphaNumericConvDict_.Add('m', 'M'); // m -> M
			AlphaNumericConvDict_.Add('n', 'N'); // n -> N
			AlphaNumericConvDict_.Add('o', 'O'); // o -> O
			AlphaNumericConvDict_.Add('p', 'P'); // p -> P
			AlphaNumericConvDict_.Add('q', 'Q'); // q -> Q
			AlphaNumericConvDict_.Add('r', 'R'); // r -> R
			AlphaNumericConvDict_.Add('s', 'S'); // s -> S
			AlphaNumericConvDict_.Add('t', 'T'); // t -> T
			AlphaNumericConvDict_.Add('u', 'U'); // u -> U
			AlphaNumericConvDict_.Add('v', 'V'); // v -> V
			AlphaNumericConvDict_.Add('w', 'W'); // w -> W
			AlphaNumericConvDict_.Add('x', 'X'); // x -> X
			AlphaNumericConvDict_.Add('y', 'Y'); // y -> Y
			AlphaNumericConvDict_.Add('z', 'Z'); // z -> Z

			#endregion

			#region KanaDictionary

			KanaConvDict_.Add('｡', new CharacterData('。', CharacterType.HasNoVariant)); // ｡ -> 。
			KanaConvDict_.Add('｢', new CharacterData('「', CharacterType.HasNoVariant)); // ｢ -> 「
			KanaConvDict_.Add('｣', new CharacterData('」', CharacterType.HasNoVariant)); // ｣ -> 」
			KanaConvDict_.Add('､', new CharacterData('、', CharacterType.HasNoVariant)); // ､ -> 、
			KanaConvDict_.Add('･', new CharacterData('・', CharacterType.HasNoVariant)); // ･ -> ・
			KanaConvDict_.Add('ｦ', new CharacterData('ヲ', CharacterType.HasNoVariant)); // ｦ -> ヲ
			KanaConvDict_.Add('ｧ', new CharacterData('ァ', CharacterType.HasNoVariant)); // ｧ -> ァ
			KanaConvDict_.Add('ｨ', new CharacterData('ィ', CharacterType.HasNoVariant)); // ｨ -> ィ
			KanaConvDict_.Add('ｩ', new CharacterData('ゥ', CharacterType.HasNoVariant)); // ｩ -> ゥ
			KanaConvDict_.Add('ｪ', new CharacterData('ェ', CharacterType.HasNoVariant)); // ｪ -> ェ
			KanaConvDict_.Add('ｫ', new CharacterData('ォ', CharacterType.HasNoVariant)); // ｫ -> ォ
			KanaConvDict_.Add('ｬ', new CharacterData('ャ', CharacterType.HasNoVariant)); // ｬ -> ャ
			KanaConvDict_.Add('ｭ', new CharacterData('ュ', CharacterType.HasNoVariant)); // ｭ -> ュ
			KanaConvDict_.Add('ｮ', new CharacterData('ョ', CharacterType.HasNoVariant)); // ｮ -> ョ
			KanaConvDict_.Add('ｯ', new CharacterData('ッ', CharacterType.HasNoVariant)); // ｯ -> ッ
			KanaConvDict_.Add('ｰ', new CharacterData('ー', CharacterType.HasNoVariant)); // ｰ -> ー

			KanaConvDict_.Add('ｱ', new CharacterData('ア', CharacterType.HasNoVariant)); // ｱ -> ア
			KanaConvDict_.Add('ｲ', new CharacterData('イ', CharacterType.HasNoVariant)); // ｲ -> イ
			KanaConvDict_.Add('ｳ', new CharacterData('ウ', CharacterType.SoundMark)); // ｳ -> ウ
			KanaConvDict_.Add('ｴ', new CharacterData('エ', CharacterType.HasNoVariant)); // ｴ -> エ
			KanaConvDict_.Add('ｵ', new CharacterData('オ', CharacterType.HasNoVariant)); // ｵ -> オ

			KanaConvDict_.Add('ｶ', new CharacterData('カ', CharacterType.HasSoundMarkedVariant)); // ｶ -> カ
			KanaConvDict_.Add('ｷ', new CharacterData('キ', CharacterType.HasSoundMarkedVariant)); // ｷ -> キ
			KanaConvDict_.Add('ｸ', new CharacterData('ク', CharacterType.HasSoundMarkedVariant)); // ｸ -> ク
			KanaConvDict_.Add('ｹ', new CharacterData('ケ', CharacterType.HasSoundMarkedVariant)); // ｹ -> ケ
			KanaConvDict_.Add('ｺ', new CharacterData('コ', CharacterType.HasSoundMarkedVariant)); // ｺ -> コ

			KanaConvDict_.Add('ｻ', new CharacterData('サ', CharacterType.HasSoundMarkedVariant)); // ｻ -> サ
			KanaConvDict_.Add('ｼ', new CharacterData('シ', CharacterType.HasSoundMarkedVariant)); // ｼ -> シ
			KanaConvDict_.Add('ｽ', new CharacterData('ス', CharacterType.HasSoundMarkedVariant)); // ｽ -> ス
			KanaConvDict_.Add('ｾ', new CharacterData('セ', CharacterType.HasSoundMarkedVariant)); // ｾ -> セ
			KanaConvDict_.Add('ｿ', new CharacterData('ソ', CharacterType.HasSoundMarkedVariant)); // ｿ -> ソ

			KanaConvDict_.Add('ﾀ', new CharacterData('タ', CharacterType.HasSoundMarkedVariant)); // ﾀ -> タ
			KanaConvDict_.Add('ﾁ', new CharacterData('チ', CharacterType.HasSoundMarkedVariant)); // ﾁ -> チ
			KanaConvDict_.Add('ﾂ', new CharacterData('ツ', CharacterType.HasSoundMarkedVariant)); // ﾂ -> ツ
			KanaConvDict_.Add('ﾃ', new CharacterData('テ', CharacterType.HasSoundMarkedVariant)); // ﾃ -> テ
			KanaConvDict_.Add('ﾄ', new CharacterData('ト', CharacterType.HasSoundMarkedVariant)); // ﾄ -> ト

			KanaConvDict_.Add('ﾅ', new CharacterData('ナ', CharacterType.HasNoVariant)); // ﾅ -> ナ
			KanaConvDict_.Add('ﾆ', new CharacterData('ニ', CharacterType.HasNoVariant)); // ﾆ -> ニ
			KanaConvDict_.Add('ﾇ', new CharacterData('ヌ', CharacterType.HasNoVariant)); // ﾇ -> ヌ
			KanaConvDict_.Add('ﾈ', new CharacterData('ネ', CharacterType.HasNoVariant)); // ﾈ -> ネ
			KanaConvDict_.Add('ﾉ', new CharacterData('ノ', CharacterType.HasNoVariant)); // ﾉ -> ノ

			KanaConvDict_.Add('ﾊ', new CharacterData('ハ', CharacterType.HasBothSoundMarkVariant)); // ﾊ -> ハ
			KanaConvDict_.Add('ﾋ', new CharacterData('ヒ', CharacterType.HasBothSoundMarkVariant)); // ﾋ -> ヒ
			KanaConvDict_.Add('ﾌ', new CharacterData('フ', CharacterType.HasBothSoundMarkVariant)); // ﾌ -> フ
			KanaConvDict_.Add('ﾍ', new CharacterData('ヘ', CharacterType.HasBothSoundMarkVariant)); // ﾍ -> ヘ
			KanaConvDict_.Add('ﾎ', new CharacterData('ホ', CharacterType.HasBothSoundMarkVariant)); // ﾎ -> ホ

			KanaConvDict_.Add('ﾏ', new CharacterData('マ', CharacterType.HasNoVariant)); // ﾏ -> マ
			KanaConvDict_.Add('ﾐ', new CharacterData('ミ', CharacterType.HasNoVariant)); // ﾐ -> ミ
			KanaConvDict_.Add('ﾑ', new CharacterData('ム', CharacterType.HasNoVariant)); // ﾑ -> ム
			KanaConvDict_.Add('ﾒ', new CharacterData('メ', CharacterType.HasNoVariant)); // ﾒ -> メ
			KanaConvDict_.Add('ﾓ', new CharacterData('モ', CharacterType.HasNoVariant)); // ﾓ -> モ

			KanaConvDict_.Add('ﾔ', new CharacterData('ヤ', CharacterType.HasNoVariant)); // ﾔ -> ヤ
			KanaConvDict_.Add('ﾕ', new CharacterData('ユ', CharacterType.HasNoVariant)); // ﾕ -> ユ
			KanaConvDict_.Add('ﾖ', new CharacterData('ヨ', CharacterType.HasNoVariant)); // ﾖ -> ヨ

			KanaConvDict_.Add('ﾗ', new CharacterData('ラ', CharacterType.HasNoVariant)); // ﾗ -> ラ
			KanaConvDict_.Add('ﾘ', new CharacterData('リ', CharacterType.HasNoVariant)); // ﾘ -> リ
			KanaConvDict_.Add('ﾙ', new CharacterData('ル', CharacterType.HasNoVariant)); // ﾙ -> ル
			KanaConvDict_.Add('ﾚ', new CharacterData('レ', CharacterType.HasNoVariant)); // ﾚ -> レ
			KanaConvDict_.Add('ﾛ', new CharacterData('ロ', CharacterType.HasNoVariant)); // ﾛ -> ロ
			KanaConvDict_.Add('ﾜ', new CharacterData('ワ', CharacterType.HasNoVariant)); // ﾜ -> ワ
			KanaConvDict_.Add('ﾝ', new CharacterData('ン', CharacterType.HasNoVariant)); // ﾝ -> ン


			KanaConvDict_.Add('゛', new CharacterData('゛', CharacterType.SoundMark)); // ﾞ -> ゛
			KanaConvDict_.Add('゜', new CharacterData('゜', CharacterType.SemiSoundMark)); // ﾟ -> ゜
			KanaConvDict_.Add('ﾞ', new CharacterData('゛', CharacterType.SoundMark)); // ﾞ -> ゛
			KanaConvDict_.Add('ﾟ', new CharacterData('゜', CharacterType.SemiSoundMark)); // ﾟ -> ゜
			KanaConvDict_.Add('ぁ', new CharacterData('ァ', CharacterType.HasNoVariant)); // ぁ -> ァ
			KanaConvDict_.Add('あ', new CharacterData('ア', CharacterType.HasNoVariant)); // あ -> ア
			KanaConvDict_.Add('ぃ', new CharacterData('ィ', CharacterType.HasNoVariant)); // ぃ -> ィ
			KanaConvDict_.Add('い', new CharacterData('イ', CharacterType.HasNoVariant)); // い -> イ
			KanaConvDict_.Add('ぅ', new CharacterData('ゥ', CharacterType.HasNoVariant)); // ぅ -> ゥ
			KanaConvDict_.Add('う', new CharacterData('ウ', CharacterType.HasSoundMarkedVariant)); // う -> ウ
			KanaConvDict_.Add('ぇ', new CharacterData('ェ', CharacterType.HasNoVariant)); // ぇ -> ェ
			KanaConvDict_.Add('え', new CharacterData('エ', CharacterType.HasNoVariant)); // え -> エ
			KanaConvDict_.Add('ぉ', new CharacterData('ォ', CharacterType.HasNoVariant)); // ぉ -> ォ
			KanaConvDict_.Add('お', new CharacterData('オ', CharacterType.HasNoVariant)); // お -> オ
			KanaConvDict_.Add('か', new CharacterData('カ', CharacterType.HasSoundMarkedVariant)); // か -> カ
			KanaConvDict_.Add('が', new CharacterData('ガ', CharacterType.HasNoVariant)); // が -> ガ
			KanaConvDict_.Add('き', new CharacterData('キ', CharacterType.HasSoundMarkedVariant)); // き -> キ
			KanaConvDict_.Add('ぎ', new CharacterData('ギ', CharacterType.HasNoVariant)); // ぎ -> ギ
			KanaConvDict_.Add('く', new CharacterData('ク', CharacterType.HasSoundMarkedVariant)); // く -> ク
			KanaConvDict_.Add('ぐ', new CharacterData('グ', CharacterType.HasNoVariant)); // ぐ -> グ
			KanaConvDict_.Add('け', new CharacterData('ケ', CharacterType.HasSoundMarkedVariant)); // け -> ケ
			KanaConvDict_.Add('げ', new CharacterData('ゲ', CharacterType.HasNoVariant)); // げ -> ゲ
			KanaConvDict_.Add('こ', new CharacterData('コ', CharacterType.HasSoundMarkedVariant)); // こ -> コ
			KanaConvDict_.Add('ご', new CharacterData('ゴ', CharacterType.HasNoVariant)); // ご -> ゴ
			KanaConvDict_.Add('さ', new CharacterData('サ', CharacterType.HasSoundMarkedVariant)); // さ -> サ
			KanaConvDict_.Add('ざ', new CharacterData('ザ', CharacterType.HasNoVariant)); // ざ -> ザ
			KanaConvDict_.Add('し', new CharacterData('シ', CharacterType.HasSoundMarkedVariant)); // し -> シ
			KanaConvDict_.Add('じ', new CharacterData('ジ', CharacterType.HasNoVariant)); // じ -> ジ
			KanaConvDict_.Add('す', new CharacterData('ス', CharacterType.HasSoundMarkedVariant)); // す -> ス
			KanaConvDict_.Add('ず', new CharacterData('ズ', CharacterType.HasNoVariant)); // ず -> ズ
			KanaConvDict_.Add('せ', new CharacterData('セ', CharacterType.HasSoundMarkedVariant)); // せ -> セ
			KanaConvDict_.Add('ぜ', new CharacterData('ゼ', CharacterType.HasNoVariant)); // ぜ -> ゼ
			KanaConvDict_.Add('そ', new CharacterData('ソ', CharacterType.HasSoundMarkedVariant)); // そ -> ソ
			KanaConvDict_.Add('ぞ', new CharacterData('ゾ', CharacterType.HasNoVariant)); // ぞ -> ゾ
			KanaConvDict_.Add('た', new CharacterData('タ', CharacterType.HasSoundMarkedVariant)); // た -> タ
			KanaConvDict_.Add('だ', new CharacterData('ダ', CharacterType.HasNoVariant)); // だ -> ダ
			KanaConvDict_.Add('ち', new CharacterData('チ', CharacterType.HasSoundMarkedVariant)); // ち -> チ
			KanaConvDict_.Add('ぢ', new CharacterData('ヂ', CharacterType.HasNoVariant)); // ぢ -> ヂ
			KanaConvDict_.Add('っ', new CharacterData('ッ', CharacterType.HasNoVariant)); // っ -> ッ
			KanaConvDict_.Add('つ', new CharacterData('ツ', CharacterType.HasSoundMarkedVariant)); // つ -> ツ
			KanaConvDict_.Add('づ', new CharacterData('ヅ', CharacterType.HasNoVariant)); // づ -> ヅ
			KanaConvDict_.Add('て', new CharacterData('テ', CharacterType.HasSoundMarkedVariant)); // て -> テ
			KanaConvDict_.Add('で', new CharacterData('デ', CharacterType.HasNoVariant)); // で -> デ
			KanaConvDict_.Add('と', new CharacterData('ト', CharacterType.HasSoundMarkedVariant)); // と -> ト
			KanaConvDict_.Add('ど', new CharacterData('ド', CharacterType.HasNoVariant)); // ど -> ド
			KanaConvDict_.Add('な', new CharacterData('ナ', CharacterType.HasNoVariant)); // な -> ナ
			KanaConvDict_.Add('に', new CharacterData('ニ', CharacterType.HasNoVariant)); // に -> ニ
			KanaConvDict_.Add('ぬ', new CharacterData('ヌ', CharacterType.HasNoVariant)); // ぬ -> ヌ
			KanaConvDict_.Add('ね', new CharacterData('ネ', CharacterType.HasNoVariant)); // ね -> ネ
			KanaConvDict_.Add('の', new CharacterData('ノ', CharacterType.HasNoVariant)); // の -> ノ
			KanaConvDict_.Add('は', new CharacterData('ハ', CharacterType.HasBothSoundMarkVariant)); // は -> ハ
			KanaConvDict_.Add('ば', new CharacterData('バ', CharacterType.HasNoVariant)); // ば -> バ
			KanaConvDict_.Add('ぱ', new CharacterData('パ', CharacterType.HasNoVariant)); // ぱ -> パ
			KanaConvDict_.Add('ひ', new CharacterData('ヒ', CharacterType.HasBothSoundMarkVariant)); // ひ -> ヒ
			KanaConvDict_.Add('び', new CharacterData('ビ', CharacterType.HasNoVariant)); // び -> ビ
			KanaConvDict_.Add('ぴ', new CharacterData('ピ', CharacterType.HasNoVariant)); // ぴ -> ピ
			KanaConvDict_.Add('ふ', new CharacterData('フ', CharacterType.HasBothSoundMarkVariant)); // ふ -> フ
			KanaConvDict_.Add('ぶ', new CharacterData('ブ', CharacterType.HasNoVariant)); // ぶ -> ブ
			KanaConvDict_.Add('ぷ', new CharacterData('プ', CharacterType.HasNoVariant)); // ぷ -> プ
			KanaConvDict_.Add('へ', new CharacterData('ヘ', CharacterType.HasBothSoundMarkVariant)); // へ -> ヘ
			KanaConvDict_.Add('べ', new CharacterData('ベ', CharacterType.HasNoVariant)); // べ -> ベ
			KanaConvDict_.Add('ぺ', new CharacterData('ペ', CharacterType.HasNoVariant)); // ぺ -> ペ
			KanaConvDict_.Add('ほ', new CharacterData('ホ', CharacterType.HasBothSoundMarkVariant)); // ほ -> ホ
			KanaConvDict_.Add('ぼ', new CharacterData('ボ', CharacterType.HasNoVariant)); // ぼ -> ボ
			KanaConvDict_.Add('ぽ', new CharacterData('ポ', CharacterType.HasNoVariant)); // ぽ -> ポ
			KanaConvDict_.Add('ま', new CharacterData('マ', CharacterType.HasNoVariant)); // ま -> マ
			KanaConvDict_.Add('み', new CharacterData('ミ', CharacterType.HasNoVariant)); // み -> ミ
			KanaConvDict_.Add('む', new CharacterData('ム', CharacterType.HasNoVariant)); // む -> ム
			KanaConvDict_.Add('め', new CharacterData('メ', CharacterType.HasNoVariant)); // め -> メ
			KanaConvDict_.Add('も', new CharacterData('モ', CharacterType.HasNoVariant)); // も -> モ
			KanaConvDict_.Add('ゃ', new CharacterData('ャ', CharacterType.HasNoVariant)); // ゃ -> ャ
			KanaConvDict_.Add('や', new CharacterData('ヤ', CharacterType.HasNoVariant)); // や -> ヤ
			KanaConvDict_.Add('ゅ', new CharacterData('ュ', CharacterType.HasNoVariant)); // ゅ -> ュ
			KanaConvDict_.Add('ゆ', new CharacterData('ユ', CharacterType.HasNoVariant)); // ゆ -> ユ
			KanaConvDict_.Add('ょ', new CharacterData('ョ', CharacterType.HasNoVariant)); // ょ -> ョ
			KanaConvDict_.Add('よ', new CharacterData('ヨ', CharacterType.HasNoVariant)); // よ -> ヨ
			KanaConvDict_.Add('ら', new CharacterData('ラ', CharacterType.HasNoVariant)); // ら -> ラ
			KanaConvDict_.Add('り', new CharacterData('リ', CharacterType.HasNoVariant)); // り -> リ
			KanaConvDict_.Add('る', new CharacterData('ル', CharacterType.HasNoVariant)); // る -> ル
			KanaConvDict_.Add('れ', new CharacterData('レ', CharacterType.HasNoVariant)); // れ -> レ
			KanaConvDict_.Add('ろ', new CharacterData('ロ', CharacterType.HasNoVariant)); // ろ -> ロ
			KanaConvDict_.Add('ゎ', new CharacterData('ヮ', CharacterType.HasNoVariant)); // ゎ -> ヮ
			KanaConvDict_.Add('わ', new CharacterData('ワ', CharacterType.HasNoVariant)); // わ -> ワ
			KanaConvDict_.Add('ゐ', new CharacterData('ヰ', CharacterType.HasNoVariant)); // ゐ -> ヰ
			KanaConvDict_.Add('ゑ', new CharacterData('ヱ', CharacterType.HasNoVariant)); // ゑ -> ヱ
			KanaConvDict_.Add('を', new CharacterData('ヲ', CharacterType.HasNoVariant)); // を -> ヲ
			KanaConvDict_.Add('ん', new CharacterData('ン', CharacterType.HasNoVariant)); // ん -> ン


			KanaConvDict_.Add('ァ', new CharacterData('ァ', CharacterType.HasNoVariant)); // ぁ -> ァ
			KanaConvDict_.Add('ア', new CharacterData('ア', CharacterType.HasNoVariant)); // あ -> ア
			KanaConvDict_.Add('ィ', new CharacterData('ィ', CharacterType.HasNoVariant)); // ぃ -> ィ
			KanaConvDict_.Add('イ', new CharacterData('イ', CharacterType.HasNoVariant)); // い -> イ
			KanaConvDict_.Add('ゥ', new CharacterData('ゥ', CharacterType.HasNoVariant)); // ぅ -> ゥ
			KanaConvDict_.Add('ウ', new CharacterData('ウ', CharacterType.HasSoundMarkedVariant)); // う -> ウ
			KanaConvDict_.Add('ェ', new CharacterData('ェ', CharacterType.HasNoVariant)); // ぇ -> ェ
			KanaConvDict_.Add('エ', new CharacterData('エ', CharacterType.HasNoVariant)); // え -> エ
			KanaConvDict_.Add('ォ', new CharacterData('ォ', CharacterType.HasNoVariant)); // ぉ -> ォ
			KanaConvDict_.Add('オ', new CharacterData('オ', CharacterType.HasNoVariant)); // お -> オ
			KanaConvDict_.Add('カ', new CharacterData('カ', CharacterType.HasSoundMarkedVariant)); // か -> カ
			KanaConvDict_.Add('ガ', new CharacterData('ガ', CharacterType.HasNoVariant)); // が -> ガ
			KanaConvDict_.Add('キ', new CharacterData('キ', CharacterType.HasSoundMarkedVariant)); // き -> キ
			KanaConvDict_.Add('ギ', new CharacterData('ギ', CharacterType.HasNoVariant)); // ぎ -> ギ
			KanaConvDict_.Add('ク', new CharacterData('ク', CharacterType.HasSoundMarkedVariant)); // く -> ク
			KanaConvDict_.Add('グ', new CharacterData('グ', CharacterType.HasNoVariant)); // ぐ -> グ
			KanaConvDict_.Add('ケ', new CharacterData('ケ', CharacterType.HasSoundMarkedVariant)); // け -> ケ
			KanaConvDict_.Add('ゲ', new CharacterData('ゲ', CharacterType.HasNoVariant)); // げ -> ゲ
			KanaConvDict_.Add('コ', new CharacterData('コ', CharacterType.HasSoundMarkedVariant)); // こ -> コ
			KanaConvDict_.Add('ゴ', new CharacterData('ゴ', CharacterType.HasNoVariant)); // ご -> ゴ
			KanaConvDict_.Add('サ', new CharacterData('サ', CharacterType.HasSoundMarkedVariant)); // さ -> サ
			KanaConvDict_.Add('ザ', new CharacterData('ザ', CharacterType.HasNoVariant)); // ざ -> ザ
			KanaConvDict_.Add('シ', new CharacterData('シ', CharacterType.HasSoundMarkedVariant)); // し -> シ
			KanaConvDict_.Add('ジ', new CharacterData('ジ', CharacterType.HasNoVariant)); // じ -> ジ
			KanaConvDict_.Add('ス', new CharacterData('ス', CharacterType.HasSoundMarkedVariant)); // す -> ス
			KanaConvDict_.Add('ズ', new CharacterData('ズ', CharacterType.HasNoVariant)); // ず -> ズ
			KanaConvDict_.Add('セ', new CharacterData('セ', CharacterType.HasSoundMarkedVariant)); // せ -> セ
			KanaConvDict_.Add('ゼ', new CharacterData('ゼ', CharacterType.HasNoVariant)); // ぜ -> ゼ
			KanaConvDict_.Add('ソ', new CharacterData('ソ', CharacterType.HasSoundMarkedVariant)); // そ -> ソ
			KanaConvDict_.Add('ゾ', new CharacterData('ゾ', CharacterType.HasNoVariant)); // ぞ -> ゾ
			KanaConvDict_.Add('タ', new CharacterData('タ', CharacterType.HasSoundMarkedVariant)); // た -> タ
			KanaConvDict_.Add('ダ', new CharacterData('ダ', CharacterType.HasNoVariant)); // だ -> ダ
			KanaConvDict_.Add('チ', new CharacterData('チ', CharacterType.HasSoundMarkedVariant)); // ち -> チ
			KanaConvDict_.Add('ヂ', new CharacterData('ヂ', CharacterType.HasNoVariant)); // ぢ -> ヂ
			KanaConvDict_.Add('ッ', new CharacterData('ッ', CharacterType.HasNoVariant)); // っ -> ッ
			KanaConvDict_.Add('ツ', new CharacterData('ツ', CharacterType.HasSoundMarkedVariant)); // つ -> ツ
			KanaConvDict_.Add('ヅ', new CharacterData('ヅ', CharacterType.HasNoVariant)); // づ -> ヅ
			KanaConvDict_.Add('テ', new CharacterData('テ', CharacterType.HasSoundMarkedVariant)); // て -> テ
			KanaConvDict_.Add('デ', new CharacterData('デ', CharacterType.HasNoVariant)); // で -> デ
			KanaConvDict_.Add('ト', new CharacterData('ト', CharacterType.HasSoundMarkedVariant)); // と -> ト
			KanaConvDict_.Add('ド', new CharacterData('ド', CharacterType.HasNoVariant)); // ど -> ド
			KanaConvDict_.Add('ナ', new CharacterData('ナ', CharacterType.HasNoVariant)); // な -> ナ
			KanaConvDict_.Add('ニ', new CharacterData('ニ', CharacterType.HasNoVariant)); // に -> ニ
			KanaConvDict_.Add('ヌ', new CharacterData('ヌ', CharacterType.HasNoVariant)); // ぬ -> ヌ
			KanaConvDict_.Add('ネ', new CharacterData('ネ', CharacterType.HasNoVariant)); // ね -> ネ
			KanaConvDict_.Add('ノ', new CharacterData('ノ', CharacterType.HasNoVariant)); // の -> ノ
			KanaConvDict_.Add('ハ', new CharacterData('ハ', CharacterType.HasBothSoundMarkVariant)); // は -> ハ
			KanaConvDict_.Add('バ', new CharacterData('バ', CharacterType.HasNoVariant)); // ば -> バ
			KanaConvDict_.Add('パ', new CharacterData('パ', CharacterType.HasNoVariant)); // ぱ -> パ
			KanaConvDict_.Add('ヒ', new CharacterData('ヒ', CharacterType.HasBothSoundMarkVariant)); // ひ -> ヒ
			KanaConvDict_.Add('ビ', new CharacterData('ビ', CharacterType.HasNoVariant)); // び -> ビ
			KanaConvDict_.Add('ピ', new CharacterData('ピ', CharacterType.HasNoVariant)); // ぴ -> ピ
			KanaConvDict_.Add('フ', new CharacterData('フ', CharacterType.HasBothSoundMarkVariant)); // ふ -> フ
			KanaConvDict_.Add('ブ', new CharacterData('ブ', CharacterType.HasNoVariant)); // ぶ -> ブ
			KanaConvDict_.Add('プ', new CharacterData('プ', CharacterType.HasNoVariant)); // ぷ -> プ
			KanaConvDict_.Add('ヘ', new CharacterData('ヘ', CharacterType.HasBothSoundMarkVariant)); // へ -> ヘ
			KanaConvDict_.Add('ベ', new CharacterData('ベ', CharacterType.HasNoVariant)); // べ -> ベ
			KanaConvDict_.Add('ペ', new CharacterData('ペ', CharacterType.HasNoVariant)); // ぺ -> ペ
			KanaConvDict_.Add('ホ', new CharacterData('ホ', CharacterType.HasBothSoundMarkVariant)); // ほ -> ホ
			KanaConvDict_.Add('ボ', new CharacterData('ボ', CharacterType.HasNoVariant)); // ぼ -> ボ
			KanaConvDict_.Add('ポ', new CharacterData('ポ', CharacterType.HasNoVariant)); // ぽ -> ポ
			KanaConvDict_.Add('マ', new CharacterData('マ', CharacterType.HasNoVariant)); // ま -> マ
			KanaConvDict_.Add('ミ', new CharacterData('ミ', CharacterType.HasNoVariant)); // み -> ミ
			KanaConvDict_.Add('ム', new CharacterData('ム', CharacterType.HasNoVariant)); // む -> ム
			KanaConvDict_.Add('メ', new CharacterData('メ', CharacterType.HasNoVariant)); // め -> メ
			KanaConvDict_.Add('モ', new CharacterData('モ', CharacterType.HasNoVariant)); // も -> モ
			KanaConvDict_.Add('ャ', new CharacterData('ャ', CharacterType.HasNoVariant)); // ゃ -> ャ
			KanaConvDict_.Add('ヤ', new CharacterData('ヤ', CharacterType.HasNoVariant)); // や -> ヤ
			KanaConvDict_.Add('ュ', new CharacterData('ュ', CharacterType.HasNoVariant)); // ゅ -> ュ
			KanaConvDict_.Add('ユ', new CharacterData('ユ', CharacterType.HasNoVariant)); // ゆ -> ユ
			KanaConvDict_.Add('ョ', new CharacterData('ョ', CharacterType.HasNoVariant)); // ょ -> ョ
			KanaConvDict_.Add('ヨ', new CharacterData('ヨ', CharacterType.HasNoVariant)); // よ -> ヨ
			KanaConvDict_.Add('ラ', new CharacterData('ラ', CharacterType.HasNoVariant)); // ら -> ラ
			KanaConvDict_.Add('リ', new CharacterData('リ', CharacterType.HasNoVariant)); // り -> リ
			KanaConvDict_.Add('ル', new CharacterData('ル', CharacterType.HasNoVariant)); // る -> ル
			KanaConvDict_.Add('レ', new CharacterData('レ', CharacterType.HasNoVariant)); // れ -> レ
			KanaConvDict_.Add('ロ', new CharacterData('ロ', CharacterType.HasNoVariant)); // ろ -> ロ
			KanaConvDict_.Add('ヮ', new CharacterData('ヮ', CharacterType.HasNoVariant)); // ゎ -> ヮ
			KanaConvDict_.Add('ワ', new CharacterData('ワ', CharacterType.HasNoVariant)); // わ -> ワ
			KanaConvDict_.Add('ヰ', new CharacterData('ヰ', CharacterType.HasNoVariant)); // ゐ -> ヰ
			KanaConvDict_.Add('ヱ', new CharacterData('ヱ', CharacterType.HasNoVariant)); // ゑ -> ヱ
			KanaConvDict_.Add('ヲ', new CharacterData('ヲ', CharacterType.HasNoVariant)); // を -> ヲ
			KanaConvDict_.Add('ン', new CharacterData('ン', CharacterType.HasNoVariant)); // ん -> ン

			#endregion
		}

		public static LiveProgramNormalizationResult Normalize(model::LiveProgram liveProgram)
		{
			if (liveProgram == null)
			{
				throw new ArgumentNullException("liveProgram");
			}

			LiveProgramNormalizationResult ret = new LiveProgramNormalizationResult();

			if (liveProgram.Title != null)
			{
				ret.Title = Normalize(liveProgram.Title);
			}

			if (liveProgram.ShortContent != null)
			{
				ret.Description = Normalize(liveProgram.ShortContent);
			}

			if (liveProgram.CasterName != null)
			{
				ret.CasterName = Normalize(liveProgram.CasterName);
			}

			if (liveProgram.Station != null)
			{
				if (liveProgram.Station.Name != null)
				{
					ret.StationName = Normalize(liveProgram.Station.Name);
				}
			}

			return ret;
		}

		public static NormalizationResult Normalize(string Source)
		{

			NormalizationResult ret = new NormalizationResult();

			if (Source == null)
			{
				ret.NFC = null;
				ret.Kana = null;
				ret.Both = null;
				ret.AlphaNumeric = null;
			}
			else
			{
				ret.NFC = Source.Normalize(NormalizationForm.FormC);

				SingleNormalize(ret);

				FullNormalize(ret);
			}

			return ret;
		}

		private static void SingleNormalize(NormalizationResult ret)
		{
			StringBuilder Alpha = new StringBuilder();
			StringBuilder Kana = new StringBuilder();

			int threshold=ret.NFC.Length-1;
			CharacterData LookAhead = null;
			char tmp = '\0';
			bool SkipFlag = false;

			for (int i = 0; i < ret.NFC.Length; i++)
			{
				tmp = ret.NFC[i];
				//alpha numeric normalize.
				if (AlphaNumericConvDict_.ContainsKey(tmp))
				{
					Alpha.Append(AlphaNumericConvDict_[tmp]);
				}
				else
				{
					Alpha.Append(tmp);
				}

				
				//Kana normalize.

				//LookAheadして､Consume済みの場合はすっ飛ばし
				if (SkipFlag)
				{
					SkipFlag = false;
					continue;
				}

				if (KanaConvDict_.ContainsKey(tmp))
				{
					CharacterData dta = KanaConvDict_[tmp];


					//ここの大前提
					//正規的な濁点､半濁点はLookAheadされたうえでConsumeされている｡
					if (dta.Type == CharacterType.HasNoVariant)
					{
						Kana.Append(dta.Character);
					}
					else if(dta.Type== CharacterType.SemiSoundMark)
					{
						Kana.Append(dta.Character);
					}
					else if (dta.Type == CharacterType.SoundMark)
					{
						Kana.Append(dta.Character);
					}
					else
					{
						//ここ以下部分的にLL(1)的な挙動
						//ここ以外で､これが走ると､単なるコストなので､ここまで遅延
						if (i < threshold)
						{
							tmp = ret.NFC[i + 1];

							if (KanaConvDict_.ContainsKey(tmp))
							{
								LookAhead = KanaConvDict_[tmp];
							}
							else
							{
								LookAhead = null;
							}
						}
						else
						{
							LookAhead = null;
						}

						//LookAheadして､SoundMarkじゃなきゃ抜ける｡
						if (LookAhead == null || (LookAhead.Type & CharacterType.AllSoundMarks) == CharacterType.None)
						{
							Kana.Append(dta.Character);
							continue;
						}

						if (LookAhead.Type == CharacterType.SoundMark)
						{
							if ((dta.Type & CharacterType.HasBothSoundMarkVariant) == CharacterType.None)
							{
								Kana.Append(dta.Character);
								continue;
							}
							else
							{
								Kana.Append(SoundConverter_[dta.Character]);
								SkipFlag = true;
							}
						}
						else if (LookAhead.Type == CharacterType.SemiSoundMark)
						{
							if ((dta.Type & CharacterType.HasSemiSoundMarkedVariant) == CharacterType.None)
							{
								Kana.Append(dta.Character);
								continue;
							}
							else
							{
								Kana.Append(SemiSoundConverter_[dta.Character]);
								SkipFlag = true;
							}
						}
						else
						{
							throw new Exception();
						}
					}
				}
				else
				{
					Kana.Append(ret.NFC[i]);
				}
			}

			ret.AlphaNumeric = Alpha.ToString();
			ret.Kana = Kana.ToString();

		}

		private static void FullNormalize(NormalizationResult ret)
		{
			StringBuilder bld = new StringBuilder();

			for (int i = 0; i < ret.Kana.Length; i++)
			{
				char tmp = ret.Kana[i];

				if (AlphaNumericConvDict_.ContainsKey(tmp))
				{
					bld.Append(AlphaNumericConvDict_[tmp]);
				}
				else
				{
					bld.Append(tmp);
				}
			}

			ret.Both = bld.ToString();
		}

	}
}
